package com.linkey.generator;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.linkey.common.custom.Constant;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @author zhangyb
 * @date {2020年6月28日16:55:30}
 */
public class Generator {

    /**==================================常用参数配置==========================================**/
    private static final String AUTHOR = "zhujh";
    private static final boolean IS_GENERATE_CONTROLLER = true; // 是否生成controller
    private static final boolean IS_GENERATE_INSERT = true;// 是否生成插入方法
    private static final boolean IS_GENERATE_UPDATE = true;// 是否生成更新方法
    private static final boolean IS_GENERATE_DELETE = true;// 是否生成删除方法
    private static final boolean IS_GENERATE_QUERYBYID = true;// 是否生成根据id查询方法
    private static final boolean IS_GENERATE_QUERYPAGE = true;// 是否生成分页方法
    private static final boolean IS_GENERATE_BATCH_DELETE = true;// 是否生成批量删除
    private static final List<String> LIKE_FIELDS = Arrays.asList("test_name");// like 字段
    private static final DbType DB_TYPE = DbType.POSTGRE_SQL; // 数据库类型
//    private static final String MAPPER_PKG = "mapper";
    private static final String MAPPER_PKG = "tsMapper";
    private static final String WEB_PROJECT = "linkey-demo";// 生成controller的工程
    private static final String PROJECT_PCK = "demo";// 包前缀
    /**==================================常用参数配置==========================================**/



    /**==================================数据库参数配置==========================================**/
//    private static final String CONNECTURL = "jdbc:mysql://106.14.214.107:3306/linkey-base?useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8";
//    private static final String USERNAME = "poris";
//    private static final String PASSWORD = "poris2020";

    private static final String CONNECTURL = "jdbc:postgresql://106.14.214.107:5432/lg_iot?currentSchema=public";
    private static final String USERNAME = "postgres";
    private static final String PASSWORD = "poris2020";
    /**==================================数据库参数配置==========================================**/



    /**==================================默认参数配置==========================================**/
    private static final String PROJECT_PATH = System.getProperty("user.dir")+"/" + WEB_PROJECT;
    private static final String PARENT_PACKAGE = "com.linkey." + PROJECT_PCK + ".services";
    private static final String RRE_PATH = "com/linkey/" + PROJECT_PCK + "/services/";
    /**==================================默认参数配置==========================================**/


    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    public static void main(String[] args) {
        String moduleName = scanner("请输入模块名");
        String[] tableNames = scanner("请输入表名（多个表用英文逗号分隔）").split(",");

        /**
         * 创建代码生成器
         */
        AutoGenerator mpg = new AutoGenerator();

        /**
         * 策略配置
         */
        StrategyConfig sc = new StrategyConfig();
        /**
         * 表名前缀
         */
        sc.setTablePrefix("");
        /**
         * 表名生成策略
         */
        sc.setNaming(NamingStrategy.underline_to_camel);
        sc.setRestControllerStyle(true);
        sc.setEntityBuilderModel(true);
        sc.setEntityLombokModel(true);
        sc.setInclude(tableNames);
        sc.setGenerateController(IS_GENERATE_CONTROLLER);
        sc.setGenerateInsert(IS_GENERATE_INSERT);
        sc.setGenerateUpdate(IS_GENERATE_UPDATE);
        sc.setGenerateDelete(IS_GENERATE_DELETE);
        sc.setTransactional(DbTypeEnum.get(DB_TYPE.getDb()).getTransactional());
        sc.setGenerateQueryById(IS_GENERATE_QUERYBYID);
        sc.setGenerateQueryPage(IS_GENERATE_QUERYPAGE);
        sc.setGenerateBatchDelete(IS_GENERATE_BATCH_DELETE);
        sc.setLogicDeleteFieldName("state");
        sc.setLikeFields(LIKE_FIELDS);
//        sc.setSuperEntityColumns("state", "create_person_id", "modify_date",
//                "modify_person_id", "delete_date", "delete_person_id");
        sc.setNotToGenerateFields(Arrays.asList("state", "create_person_id", "modify_date",
                "modify_person_id", "delete_date", "delete_person_id"));

        mpg.setStrategy(sc);

        //指定模板引擎  默认velocity

        /**
         * 全局配置
         */
        GlobalConfig gc = new GlobalConfig();
        gc.setOpen(false);
        gc.setOutputDir(PROJECT_PATH + "/src/main/java/");
        gc.setServiceName("%sService");
        gc.setServiceImplName("%sServiceImpl");
        gc.setAuthor(AUTHOR);
//        gc.setIdType(IdType.ASSIGN_ID);
        gc.setDateType(DateType.ONLY_DATE);
        mpg.setGlobalConfig(gc);
        /**
         * 数据源配置
         */
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DB_TYPE);
        dsc.setDriverName(DbTypeEnum.get(DB_TYPE.getDb()).getDriverName());
        dsc.setUrl(CONNECTURL);
        dsc.setUsername(USERNAME);
        dsc.setPassword(PASSWORD);
        mpg.setDataSource(dsc);
        /**
         * 包配置
         */
        PackageConfig pc = new PackageConfig();
        pc.setParent(PARENT_PACKAGE);
        pc.setModuleName(moduleName);
        pc.setMapper(MAPPER_PKG);
        pc.setService("service");
        pc.setServiceImpl("service.impl");
        mpg.setPackageInfo(pc);

        /**
         * 自定义配置
         */
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        /**
         *  自定义输出配置
         */
        List<FileOutConfig> focList = new ArrayList<>();

        String templatePathMapperJava = "/templates/mapper.java.vm";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePathMapperJava) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return gc.getOutputDir() + RRE_PATH + moduleName + "/" + MAPPER_PKG + "/"
                        + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_JAVA;
            }
        });

        /**
         * 如果模板引擎是 vm
         */
        String templatePath = "/templates/mapper.xml.vm";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return PROJECT_PATH + "/src/main/resources/" + MAPPER_PKG + "/" + moduleName + "/"
                        + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        String templatePathEnumJava = "/templates/enum.java.vm";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePathEnumJava) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return gc.getOutputDir() + RRE_PATH + moduleName + "/enums/"
                        + tableInfo.getEnumName() + StringPool.DOT_JAVA;
            }
        });

        String templatePathInsertOrUpdateDtoJava = "/templates/insertDto.java.vm";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePathInsertOrUpdateDtoJava) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return gc.getOutputDir() + RRE_PATH + moduleName + "/dto/"
                        + tableInfo.getEntityName() + "InsertDTO" + StringPool.DOT_JAVA;
            }
        });

        String templatePathQueryByIdVoJava = "/templates/queryByIdVo.java.vm";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePathQueryByIdVoJava) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return gc.getOutputDir() + RRE_PATH + moduleName + "/vo/"
                        + tableInfo.getEntityName() + "VO" + StringPool.DOT_JAVA;
            }
        });

        String templatePathQueryPageDtoJava = "/templates/queryPageDto.java.vm";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePathQueryPageDtoJava) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return gc.getOutputDir() + RRE_PATH + moduleName + "/dto/"
                        + tableInfo.getEntityName() + "PageDTO" + StringPool.DOT_JAVA;
            }
        });

        String templatePathQueryPageVoJava = "/templates/queryPageVo.java.vm";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePathQueryPageVoJava) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return gc.getOutputDir() + RRE_PATH + moduleName + "/vo/"
                        + tableInfo.getEntityName() + "PageVO" + StringPool.DOT_JAVA;
            }
        });


//        String templatePathServiceJava = "/templates/service.java.vm";
//        // 自定义配置会被优先输出
//        focList.add(new FileOutConfig(templatePathServiceJava) {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
//                return PROJECT_PATH + "/src/main/java/" + RRE_PATH + moduleName + "/service/"
//                        + tableInfo.getEntityName() + "Service" + StringPool.DOT_JAVA;
//            }
//        });
//
//        String templatePathServiceImplJava = "/templates/serviceImpl.java.vm";
//        // 自定义配置会被优先输出
//        focList.add(new FileOutConfig(templatePathServiceImplJava) {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
//                return SERVICE_PATH_PRE + moduleName + "/service/impl/"
//                        + tableInfo.getEntityName() + "ServiceImpl" + StringPool.DOT_JAVA;
//            }
//        });

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        /**
         * 配置模板
         */
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        templateConfig.setMapper(null);
//        templateConfig.setController(null);
//        templateConfig.setEntity(null);
//        templateConfig.setEnumName(null);
        mpg.setTemplate(templateConfig);

        mpg.execute();
    }

    enum DbTypeEnum {
        MYSQL("mysql", "com.mysql.cj.jdbc.Driver", Constant.MYSQL_DB),
        TIME_SACLE("postgresql", "org.postgresql.Driver", Constant.TIMESCALE_DB),
        ;

        private final String key;
        private final String driverName;
        private final String transactional;

        DbTypeEnum(String key, String driverName, String transactional) {
            this.key = key;
            this.driverName = driverName;
            this.transactional = transactional;
        }

        public String getKey() {
            return key;
        }

        public String getDriverName() {
            return driverName;
        }

        public String getTransactional() {
            return transactional;
        }

        static public DbTypeEnum get(String key) {
            for (DbTypeEnum e : DbTypeEnum.values()) {
                if (e.getKey().equals(key)) {
                    return e;
                }
            }
            return MYSQL;
        }

    }
}
